import xeUtils from 'xe-utils'
const x_PI = 3.14159265358979324 * 3000.0 / 180.0;
/***
 * 中国正常坐标系GCJ02协议的坐标，转到 百度地图对应的 BD09 协议坐标
 * @param point
 * @returns {{lng: number, lat: number}}
 */
export const baiDuCoordinates = (point) => {
  const lng = point.lng
  const lat = point.lat
  const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI)
  const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI)
  const bd_lng = z * Math.cos(theta) + 0.0065
  const bd_lat = z * Math.sin(theta) + 0.006
  return { lng: bd_lng, lat: bd_lat }
}
/***
 * 百度地图对应的 BD09 协议坐标，转到 中国正常坐标系GCJ02协议的坐标
 * @param point
 * @returns {{lng: number, lat: number}}
 */
export const gaoDeCoordinates = (point) => {
  const bd_lon = point.lng
  const bd_lat = point.lat
  const x_pi = 3.14159265358979324 * 3000.0 / 180.0
  const x = bd_lon - 0.0065
  const y = bd_lat - 0.006
  const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi)
  const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi)
  const gg_lng = z * Math.cos(theta)
  const gg_lat = z * Math.sin(theta)
  return { lng: gg_lng, lat: gg_lat}
}
/***
 * 计算两点距离
 * @param lat1 纬度1
 * @param lng1 经度1
 * @param lat2 纬度2
 * @param lng2 经度2
 * @returns {number} 米
 * @constructor
 */
export const getDistance = ( lat1,  lng1,  lat2,  lng2 ) => {
  const radLat1 = lat1*Math.PI / 180.0;
  const radLat2 = lat2*Math.PI / 180.0;
  const a = radLat1 - radLat2;
  const b = lng1*Math.PI / 180.0 - lng2*Math.PI / 180.0;
  let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
    Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
  s = s *6378.137 ;// EARTH_RADIUS;
  s = Math.round(s * 10000) / 10000;
  s = s * 1000
  return s;
}

/**
 * @returns {String} 当前浏览器名称
 */
export const getExplorer = () => {
  const ua = window.navigator.userAgent
  const isExplorer = (exp) => {
    return ua.indexOf(exp) > -1
  }
  if (isExplorer('MSIE')) return 'IE'
  else if (isExplorer('Firefox')) return 'Firefox'
  else if (isExplorer('Chrome')) return 'Chrome'
  else if (isExplorer('Opera')) return 'Opera'
  else if (isExplorer('Safari')) return 'Safari'
}
/**
 * 把关系数组过滤成树形数据
 * @param data  原始数据
 * @param children_key  孩子的键名/默认是children
 * @param id_key  id的键名/默认是id
 * @param pid_key 储存上级的键名/默认pid
 * @returns {Array} 组装后的数据
 */
export const toTree = (data, children_key, id_key, pid_key) => {
  let child_key = children_key || 'children'
  let id = id_key || 'id'
  let pid = pid_key || 'pid'
  data.forEach(function (item) {
    delete item[child_key]
  })
  let map = {}
  data.forEach(function (item) {
    map[item[id]] = item
  })
  let val = []
  data.forEach(function (item) {
    let parent = map[item[pid]]
    if (parent) {
      (parent[child_key] || (parent[child_key] = [])).push(item)
    } else {
      val.push(item)
    }
  })
  return val
}
/**
 * 递归遍历树形结构数据
 * @param arr 要遍历的数组，遍历之后会直接更改这个数据
 * @param value 判断的值
 * @param id_key  用那个键值判断/默认id
 * @param update_key 需要更改的键值
 * @param update_value  需要更改的内容
 * @param child_key 树形结构孩子的键值
 */
export const treeFind = (arr, value, id_key, update_key, update_value, child_key) => {
  let id = id_key || 'id'
  child_key = child_key || 'children'
  if (update_key === '' || update_key === undefined || update_key === null) {
    console.log('调用treeFind方法【update_key】必须传递')
    return false
  }
  arr.forEach((item) => {
    if (item[id] === value) {
      item[update_key] = update_value
      return true
    } else if (item[child_key] && item[child_key].length > 0) {
      treeFind(item[child_key], value, id_key, update_key, update_value, child_key)
    }
  })
}
/**
 *
 * @param a 数据源
 * @param idStr 当前的主键key
 * @param pidStr 存放主键的key
 * @param chindrenStr 孩子的标志
 * @returns {Array} 新的数据
 */
export const transData = (a, idStr, pidStr, chindrenStr) => {
  let r = []
  let hash = {}
  let id = idStr
  let pid = pidStr
  let children = chindrenStr
  let i = 0
  let j = 0
  let len = a.length

  for (; i < len; i++) {
    hash[a[i][id]] = a[i]
  }

  for (; j < len; j++) {
    let aVal = a[j]
    let hashVP = hash[aVal[pid]]

    if (hashVP) {
      !hashVP[children] && (hashVP[children] = [])
      hashVP[children].push(aVal)
    } else {
      r.push(aVal)
    }
  }
  return r
}

export const getDomain = (the_url) => {
  if (the_url.search('http') !== -1) {
    let first_split = the_url.split('//')
    let without_resource = first_split[1]
    let second_split = without_resource.split('/')
    let domain = second_split[0]
    return domain
  } else {
    return false
  }
}
// 姓名脱敏
export const noSensitiveName = (str) => {
  // 消除空格
  if (str) {
    str = str.toString().trim()
  } else {
    return false
  }
  if (str !== null && str !== undefined) {
    if (str.length <= 3) {
      return '*' + str.substring(1, str.length)
    } else if (str.length > 3 && str.length <= 6) {
      return '**' + str.substring(2, str.length)
    } else if (str.length > 6) {
      return str.substring(0, 2) + '****' + str.substring(6, str.length)
    }
  } else {
    return ''
  }
}
// 校验手机号
export const identityMobile = (code) => {
  // console.log('校验手机号', code)
  // 消除空格
  if (code) {
    code = code.toString().trim()
  } else {
    return false
  }
  let patrn = /(^0{0,1}1[3|4|5|6|7|8|9][0-9]{9}$)/
  if (!patrn.exec(code)) {
    return false
  } else {
    return true
  }
}
// 校验身份证号是否是沈阳的
export const identityCardnoSY = (code) => {
  // console.log('校验是否沈阳的证件号', code)
  // 消除空格
  if (code) {
    code = code.toString().trim()
    // 已#号替换x
    if (code.indexOf('#') > 0) {
      code = code.replace('#', 'X')
    }
  } else {
    return false
  }
  if (code.substr(0, 4) === '2101') {
    return true
  } else {
    return false
  }
}

// 校验体温
export const identityTemp = code => {
  // 消除空格
  if (code) {
    code = code.toString().trim()
  } else {
    return false
  }
  // 体温区间为35-44
  const patrn = /(^((3[5-9]|4[0-3])(\.\d{1})?)$)|(^44$)/
  if (!patrn.exec(code)) {
    return false
  } else {
    return true
  }
}

// 校验身份证号
export const identityCodeValid = (code) => {
// 消除空格
  if (code) {
    code = code.toString().trim()
    // 已#号替换x
    if (code.indexOf('#') > 0) {
      code = code.replace('#', 'X')
    }
  } else {
    return false
  }

  let city = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江 ',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北 ',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏 ',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外 '
  }
  let tip = ''
  let pass = true

  if (!code || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(code)) {
    tip = '身份证号格式错误'
    pass = false
  } else if (!city[code.substr(0, 2)]) {
    tip = '身份证号地址编码错误'
    pass = false
  } else {
    // 18位身份证需要验证最后一位校验位
    if (code.length === 18) {
      code = code.split('')
      // ∑(ai×Wi)(mod 11)
      // 加权因子
      let factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
      // 校验位
      let parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
      let sum = 0
      let ai = 0
      let wi = 0
      for (let i = 0; i < 17; i++) {
        ai = code[i]
        wi = factor[i]
        sum += ai * wi
      }

      let last = parity[sum % 11]
      // 身份证校验位
      let lastCode = code[17]
      if (!/^[0-9]*$/.test(last)) {
        last = last.toLowerCase()
      }
      if (!/^[0-9]*$/.test(lastCode)) {
        lastCode = lastCode.toLowerCase()
      }
      if (last.toString() !== lastCode) {
        tip = '校验位错误'
        pass = false
      }
    }
  }
  // console.log(tip, '--', pass)
  return {
    tip: tip,
    pass: pass
  }
}
/**
 * 根据身份证号获取生日
 * @param identityCard 身份证号
 * @returns {int} 年龄
 */
export const getBirthByIdCard = (identityCard) => {
  let len = (identityCard + '').length
  if (len === 0) {
    return 0
  } else {
    // 身份证号码只能为15位或18位其它不合法
    if ((len !== 15) && (len !== 18)) {
      return 0
    }
  }
  let strBirthday = ''
  // 处理18位的身份证号码从号码中得到生日
  if (len === 18) {
    strBirthday = identityCard.substr(6, 4) + '-' + identityCard.substr(10, 2) + '-' + identityCard.substr(12, 2)
  }
  if (len === 15) {
    strBirthday = '19' + identityCard.substr(6, 2) + '-' + identityCard.substr(8, 2) + '-' + identityCard.substr(10, 2)
  }
  return strBirthday
}
/**
 * 根据身份证号获取年龄
 * @param identityCard 身份证号
 * @returns {int} 年龄
 */
export const getAgeByIdCard = (identityCard) => {
  let len = (identityCard + '').length
  if (len === 0) {
    return 0
  } else {
    // 身份证号码只能为15位或18位其它不合法
    if ((len !== 15) && (len !== 18)) {
      return 0
    }
  }
  let strBirthday = ''
  // 处理18位的身份证号码从号码中得到生日
  if (len === 18) {
    strBirthday = identityCard.substr(6, 4) + '/' + identityCard.substr(10, 2) + '/' + identityCard.substr(12, 2)
  }
  if (len === 15) {
    strBirthday = '19' + identityCard.substr(6, 2) + '/' + identityCard.substr(8, 2) + '/' + identityCard.substr(10, 2)
  }
  // 时间字符串里，必须是“/”
  let birthDate = new Date(strBirthday)
  let nowDateTime = new Date()
  let age = nowDateTime.getFullYear() - birthDate.getFullYear()
  // 再考虑月、天的因素;.getMonth()获取的是从0开始的，这里进行比较，不需要加1
  if (nowDateTime.getMonth() < birthDate.getMonth() || (nowDateTime.getMonth() === birthDate.getMonth() && nowDateTime.getDate() < birthDate.getDate())) {
    age--
  }
  return age
}
/**
 * 根据身份证号获取性别
 * @param identityCard 身份证号
 */
export const getSexByIdCard = (identityCard) => {
  let sexno = ''
  let code = ''
  let name = ''
  if (identityCard.length === 18) {
    sexno = identityCard.substring(16, 17)
  } else if (identityCard.length === 15) {
    sexno = identityCard.substring(14, 15)
  } else {
    // alert('错误的身份证号码，请核对！')
    return false
  }
  let tempid = sexno % 2
  if (tempid === 0) {
    name = '女'
    code = '2'
  } else {
    name = '男'
    code = '1'
  }
  return { code: code, name: name }
}

export const drawCertQrCode = ({
  id, // canvas 绘制层ID
  color = '#000000', // 二维码颜色
  logoID = null, // logo图标ID
  multi = 1, // 放大比例
  codeContent, // 由请求响应包得到，绘制内容
  width = 101, // 由请求响应包 width得到，非固定值
  widthBlock = 4 // 白边为4个模块，是标准，下面做图片放大时候会自动放大
}) => {
  const white = '#ffffff'
  const black = color
  const canvas = document.getElementById(id) // 创建canvas对象
  const ctx = canvas.getContext('2d')
  // 绘制二维码区域
  const canvasWidth = (width + widthBlock * 2) * multi

  // 绘制白色底图
  canvas.width = canvas.height = canvasWidth
  ctx.fillStyle = '#ffffff'
  ctx.fillRect(0, 0, canvasWidth, canvasWidth)

  const sourceBytes = strToInt8Array(codeContent) // base64解码

  // 填充数据
  const n = width
  const wid = Math.ceil(n / 8) // 每一行的字节数
  for (let i = 0; i < n; i++) {
    // 高循环
    const ln = i * wid
    for (let j = 0; j < n; j++) {
      // 宽循环
      const k = ln + parseInt(j / 8, 10) // 像素点所在的字节下标
      // sourceBytes[k] 像素点所在的字节
      const color = (sourceBytes[k] & (1 << (7 - (j % 8)))) === 0 ? white : black
      ctx.fillStyle = color
      ctx.fillRect(
        (j + widthBlock) * multi,
        (i + widthBlock) * multi,
        multi,
        multi
      )
    }
  }
  if (logoID) {
    const logoImg = document.getElementById(logoID)
    const logoWidth = logoImg.width
    const logoHeight = logoImg.height
    const ctxWidth = canvas.width
    const ctxHeight = canvas.height
    ctx.drawImage(
      logoImg,
      (ctxWidth - logoWidth) / 2,
      (ctxHeight - logoHeight) / 2
    )
  }
}

export const strToInt8Array = (str) => {
  let binary_string = window.atob(str)
  let len = binary_string.length
  let bytes = new Uint8Array(len)
  for (let i = 0; i < len; i++) {
    bytes[i] = binary_string.charCodeAt(i)
  }
  return new Int8Array(bytes.buffer)
}
